import json
import xmindparser
import re
from typing import Dict, List, Any, Optional


class XMindLeafNodeExtractor:
    """XMind文件叶子节点名称提取器"""

    def __init__(self, file_path: str):
        self.file_path = file_path
        self.raw_data = None
        self.leaf_node_names = []

    def extract_leaf_node_names(self, remove_duplicates: bool = True) -> List[str]:
        """提取XMind文件中所有叶子节点的名称"""
        try:
            # 使用xmindparser读取文件
            self.raw_data = xmindparser.xmind_to_dict(self.file_path)

            # 重置叶子节点列表
            self.leaf_node_names = []

            # 遍历所有sheet处理
            for sheet_index, sheet in enumerate(self.raw_data):
                root_topic = sheet.get('topic', {})
                if root_topic:
                    self._find_leaf_nodes(root_topic)

            # 去重并保持顺序
            if remove_duplicates:
                self.leaf_node_names = self._remove_duplicates_keep_order(self.leaf_node_names)

            return self.leaf_node_names

        except Exception as e:
            print(f"提取叶子节点失败: {e}")
            return []

    def _find_leaf_nodes(self, topic: Dict):
        """递归查找叶子节点"""
        title = topic.get('title', '无标题')
        children = topic.get('topics', [])

        # 如果没有子节点，则为叶子节点
        if not children:
            # 清理标题中的规则标记（如【单选】、【多选】等）
            clean_title = self._clean_title(title)
            self.leaf_node_names.append(clean_title)
        else:
            # 如果有子节点，递归处理每个子节点
            for child_topic in children:
                self._find_leaf_nodes(child_topic)

    def _remove_duplicates_keep_order(self, names: List[str]) -> List[str]:
        """去重并保持原有顺序"""
        seen = set()
        unique_names = []
        for name in names:
            if name not in seen:
                seen.add(name)
                unique_names.append(name)
        return unique_names

    def _clean_title(self, title: str) -> str:
        """清理标题中的规则标记"""
        # 移除所有【】内容
        pattern = r'【([^】]+)】'
        clean_title = re.sub(pattern, '', title).strip()
        return clean_title

    def save_leaf_names_to_file(self, output_path: str, leaf_names: List[str], include_index: bool = True) -> bool:
        """保存叶子节点名称到文件"""
        try:
            with open(output_path, 'w', encoding='utf-8') as f:
                if include_index:
                    for i, name in enumerate(leaf_names, 1):
                        f.write(f"{i:3d}. {name}\n")
                else:
                    for name in leaf_names:
                        f.write(f"{name}\n")
            print(f"叶子节点名称已保存到: {output_path}")
            return True
        except Exception as e:
            print(f"保存文件失败: {e}")
            return False

    def save_leaf_names_to_json(self, output_path: str, leaf_names: List[str]) -> bool:
        """保存叶子节点名称到JSON文件"""
        try:
            data = {
                "total_count": len(leaf_names),
                "unique_count": len(leaf_names),  # 已经去重，所以总数就是唯一数
                "leaf_node_names": leaf_names
            }
            with open(output_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
            print(f"叶子节点名称JSON已保存到: {output_path}")
            return True
        except Exception as e:
            print(f"保存JSON文件失败: {e}")
            return False

    def print_leaf_names(self, leaf_names: List[str], show_duplicates_info: bool = True):
        """打印叶子节点名称"""
        print(f"\n🍃 找到 {len(leaf_names)} 个唯一的叶子节点:")
        print("=" * 60)
        for i, name in enumerate(leaf_names, 1):
            print(f"{i:3d}. {name}")
        print("=" * 60)

        if show_duplicates_info:
            print(f"📊 统计信息: 共 {len(leaf_names)} 个唯一节点（已自动去重并保持顺序）")


def extract_xmind_leaf_nodes(file_path: str, remove_duplicates: bool = True) -> List[str]:
    """
    提取XMind文件中所有叶子节点的名称

    Args:
        file_path: XMind文件路径
        remove_duplicates: 是否去重，默认True

    Returns:
        List[str]: 叶子节点名称列表（已去重并保持顺序）
    """
    extractor = XMindLeafNodeExtractor(file_path)
    leaf_names = extractor.extract_leaf_node_names(remove_duplicates)

    # 打印结果
    extractor.print_leaf_names(leaf_names)

    # 保存到文件（带序号）
    extractor.save_leaf_names_to_file("leaf_node_names_unique_ordered.txt", leaf_names, include_index=True)
    # 保存到文件（不带序号）
    extractor.save_leaf_names_to_file("leaf_node_names_unique_plain.txt", leaf_names, include_index=False)
    # 保存JSON格式
    extractor.save_leaf_names_to_json("leaf_node_names_unique.json", leaf_names)

    return leaf_names


# 使用示例
def main():
    """主函数 - 使用示例"""
    # 替换为你的XMind文件路径
    file_path = "D:\\project_file\\诊断式学习\\全部.xmind"

    print("🔍 开始提取XMind文件中的叶子节点...")

    # 方法1：使用便捷函数
    leaf_names = extract_xmind_leaf_nodes(file_path)

    # 方法2：使用类的方式（更多控制）
    # extractor = XMindLeafNodeExtractor(file_path)
    # leaf_names = extractor.extract_leaf_node_names()
    # extractor.print_leaf_names(leaf_names)
    # extractor.save_leaf_names_to_file("custom_leaf_names.txt", leaf_names)

    if leaf_names:
        print(f"\n✅ 成功提取 {len(leaf_names)} 个唯一的叶子节点名称")
        print("\n📁 文件保存摘要:")
        print("  ✓ leaf_node_names_unique_ordered.txt - 叶子节点名称列表（带序号）")
        print("  ✓ leaf_node_names_unique_plain.txt - 叶子节点名称列表（纯文本）")
        print("  ✓ leaf_node_names_unique.json - 叶子节点名称列表（JSON格式）")

        # 显示前10个叶子节点作为预览
        print(f"\n👀 前10个唯一叶子节点预览:")
        for i, name in enumerate(leaf_names[:10], 1):
            print(f"  {i}. {name}")
        if len(leaf_names) > 10:
            print(f"  ... 还有 {len(leaf_names) - 10} 个节点")
    else:
        print("❌ 未找到叶子节点或提取失败")


if __name__ == "__main__":
    main()